#include "bodypart.h"
#include "critterb.h"
#include "food.h"

Bodypart::Bodypart(btDynamicsWorld* ownerWorld, Bodyowner* bodyowner, const btVector3& dimensions, float weight_in, btTransform& offset, btTransform& transform, BeColor color_in, entityType ownertype)
  : Entity(ownertype, color_in)
{
	m_ownerWorld = ownerWorld;
  weight = weight_in;

	shape = new btBoxShape( dimensions );

	btVector3 localInertia(0,0,0);
	if (weight != 0.f) // weight of non zero = dynamic
		shape->calculateLocalInertia(weight,localInertia);

	myMotionState = new btDefaultMotionState(offset*transform);
	
	btRigidBody::btRigidBodyConstructionInfo rbInfo(weight,myMotionState,shape,localInertia);
  //rbInfo.m_additionalDamping = true;
  //rbInfo.m_additionalDampingFactor = 0.1f;
	body = new btRigidBody(rbInfo);

  const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
  halfExtent = boxShape->getHalfExtentsWithMargin();

  // Has to be cast to Entity* for RTTI to continue to allow dynamic_cast<>
	body->setUserPointer(dynamic_cast<Entity*>(this));
	body->setDamping(0.1f, 0.5f);
	body->setDeactivationTime(0.001);
	body->setSleepingThresholds(1.6, 2.5);

	m_ownerWorld->addRigidBody(body);

  owner = bodyowner;

  isPicked(false);

}

void Bodypart::changeScale(float scale)
{
  m_ownerWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(body->getBroadphaseHandle(),m_ownerWorld->getDispatcher());
  m_ownerWorld->removeRigidBody(body);
  delete body;

  shape->setLocalScaling(btVector3(scale,scale,scale));

	btVector3 localInertia(0,0,0);
	if (weight != 0.f) // weight of non zero = dynamic
		shape->calculateLocalInertia(weight,localInertia);


  btRigidBody::btRigidBodyConstructionInfo rbInfo(weight,myMotionState,shape,localInertia);
  body = new btRigidBody(rbInfo);
  const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
  halfExtent = boxShape->getHalfExtentsWithMargin();

  // Has to be cast to Entity* for RTTI to continue to allow dynamic_cast<>
	body->setUserPointer(dynamic_cast<Entity*>(this));
	body->setDamping(0.05, 0.85);
	body->setDeactivationTime(0.001);
	body->setSleepingThresholds(1.6, 2.5);

	m_ownerWorld->addRigidBody(body);
}

Bodypart::~Bodypart()
{
	// Remove all bodies and shapes
	m_ownerWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(body->getBroadphaseHandle(),m_ownerWorld->getDispatcher());
	m_ownerWorld->removeRigidBody(body);
	delete myMotionState;
	delete shape;
// 	delete body->getMotionState();
	delete body;
}


Food* Bodypart::getOwner_food() { return dynamic_cast<Food*>(owner); };
CritterB* Bodypart::getOwner_critter() { return dynamic_cast<CritterB*>(owner); };

void Bodypart::draw()
{
  draw(0);
}

void Bodypart::draw(int colorsel)
{
  int colorcount = colors.size();
  if(colorsel >= colorcount)
    colorsel = colorcount-1;
  if(colorsel < 0)
  {
    cerr << "Bodypart missing color(s)" << endl;
    return;
  }

	glColor4f( colors[colorsel].r, colors[colorsel].g, colors[colorsel].b, colors[colorsel].a );
	myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(position);
	glPushMatrix(); 

	Displaylists::Instance()->glMultiMatrix(position);
  glScaled(halfExtent[0], halfExtent[1], halfExtent[2]);
	Displaylists::Instance()->call(1);

	glPopMatrix();
}


float Bodypart::beEaten(float amount)
{
  return owner->beEaten(amount);
}


unsigned int Bodypart::registerInputs(BrainzArch* ba, unsigned int nextid) 
{ 
  //cerr << "Bodypart::registerInputs " << nextid << endl; 
  return nextid; 
}

unsigned int Bodypart::procInputs(Brainz& brain, unsigned int nindex) 
{ 
  return nindex; 
}

unsigned int Bodypart::registerOutputs(BrainzArch* ba, unsigned int nextid) 
{ 
  //cerr << "Bodypart::registerOutputs " << nextid << endl; 
  return nextid; 
}

unsigned int Bodypart::procOutputs(Brainz& brain, unsigned int nindex) { return nindex; }
unsigned int Bodypart::getNumberOfInputs() { return 0; }
unsigned int Bodypart::getNumberOfOutputs() { return 0; }



